<template>
    <div class="wrapper">
        <div id="container" ref="container"></div>
        <div class="btn-list">
            <button class="btn" @click="addNode({}, true)">add</button>
            <button class="btn" @click="save">保存</button>
        </div>
    </div>
</template>

<script>
import { Graph, Model } from "@antv/x6";
import { DagreLayout } from "@antv/layout";

export default {
    name: "",
    data () {
        return {
            graph: null,
            nodes: [],
            edges: [],
            node_width: 160,
            node_height: 32,
            edge_padding: 20, // 连线的padding
            portAttrs: {
                circle: {
                    magnet: true,
                    r: 5,
                    stroke: "#31d0c6",
                    strokeWidth: 2,
                    fill: "#fff",
                    style: {
                        visibility: "hidden"
                    }
                }
            }
        };
    },
    methods: {
        // mock一些数据
        getData () {
            this.nodes = [
                { id: "node1", label: "节点1", x: 520, y: 290 },
                { id: "node2", label: "节点2", x: 290, y: 180 },
                { id: "node3", label: "节点3", x: 730, y: 180 },
                { id: "node4", label: "节点4", x: 280, y: 440 },
                { id: "node5", label: "节点5", x: 520, y: 430 },
                { id: "node6", label: "节点6", x: 740, y: 430 },
                { id: "node7", label: "节点7", x: 280, y: 602 },
                { id: "node8", label: "节点8", x: 530, y: 602 }
            ];
            this.edges = [
                { source: "node1", target: "node4" },
                { source: "node1", target: "node5" },
                { source: "node1", target: "node6" },
                { source: "node1", target: "node2" },
                { source: "node1", target: "node3" },
                { source: "node4", target: "node7" },
                { source: "node4", target: "node8" },
                { source: "node1", target: "node8" }
            ];
        },
        // 保存
        save () {
            const nodesArr = [];
            const nodes = this.graph.getNodes();
            nodes.forEach(node => {
                nodesArr.push({
                    id: node.id,
                    label: node.label,
                    ...node.position()
                });
            });

            const edgesArr = [];
            const edges = this.graph.getEdges();
            edges.forEach(edge => {
                edgesArr.push({
                    source: edge.getSource().cell,
                    target: edge.getTarget().cell
                });
            });
            const graphData = { nodesArr, edgesArr };
            localStorage.setItem("graphData", JSON.stringify(graphData));
        },
        // graph初始化
        initGraph () {
            this.graph = new Graph({
                container: this.$refs.container,
                width: 1300,
                height: 800,
                grid: {
                    size: 10,
                    visible: true
                },
                panning: true,
                snapline: true,
                connecting: {
                    allowBlank: false,
                    allowMulti: false,
                    router: {
                        name: "er",
                        args: {
                            offset: "center"
                        }
                    }
                }
            });
            // 注册事件
            this.registEvents();
            // 新增节点
            this.nodes.forEach(item => {
                this.addNode(item);
            });
            // 新增边
            this.addEdge();
        },
        // 增加节点
        addNode (item, isNew) {
            this.graph.addNode({
                id: item.id || `node${this.nodes.length + 1}`,
                x: item.x || 0,
                y: item.y || 0,
                width: this.node_width,
                height: this.node_height,
                label: item.label || `节点${this.nodes.length + 1}`,
                attrs: {
                    body: {
                        fill: "#f5f5f5",
                        stroke: "#d9d9d9",
                        strokeWidth: 1
                    },
                    label: {
                        fontSize: 12
                    }
                },
                ports: {
                    groups: {
                        top: {
                            attrs: this.portAttrs,
                            zIndex: 10,
                            position: {
                                name: "top"
                            }
                        },
                        right: {
                            attrs: this.portAttrs,
                            zIndex: 10,
                            position: {
                                name: "right"
                            }
                        },
                        bottom: {
                            attrs: this.portAttrs,
                            zIndex: 10,
                            position: {
                                name: "bottom"
                            }
                        },
                        left: {
                            attrs: this.portAttrs,
                            zIndex: 10,
                            position: {
                                name: "left"
                            }
                        }
                    },
                    items: [
                        { id: "top", group: "top" },
                        { id: "right", group: "right" },
                        { id: "bottom", group: "bottom" },
                        { id: "left", group: "left" }
                    ]
                }
            });
            isNew && this.nodes.push(item);
        },
        // 新增边
        addEdge () {
            this.edges.forEach(edge => {
                this.graph.addEdge({
                    source: edge.source,
                    target: edge.target,
                    router: {
                        name: "er",
                        args: {
                            offset: "center"
                        }
                    },
                    connector: {
                    },
                    zIndex: 1
                });
            });
        },
        // 注册一些事件
        registEvents () {
            // 显示/隐藏事件
            const showPorts = (ports, show) => {
                for (let i = 0, len = ports.length; i < len; i++) {
                    ports[i].style.visibility = show ? "visible" : "hidden";
                }
            };
            // 鼠标移入，显示连接桩
            this.graph.on("node:mouseenter", ({ e, node, view }) => {
                const ports = this.$refs.container.querySelectorAll(".x6-port-body");
                showPorts(ports, true);

                const edges = this.graph.getConnectedEdges(node);
                edges.forEach(edge => {
                    edge.setAttrs({
                        line: {
                            stroke: "red"
                        }
                    });
                    edge.setZIndex(11);
                });
            });
            // 鼠标移出，隐藏连接桩
            this.graph.on("node:mouseleave", ({ e, node, view }) => {
                const ports = this.$refs.container.querySelectorAll(".x6-port-body");
                showPorts(ports, false);

                const edges = this.graph.getConnectedEdges(node);
                edges.forEach(edge => {
                    edge.setAttrs({
                        line: {
                            stroke: "#333333"
                        }
                    });
                    edge.setZIndex(1);
                });
            });
            // 节点移动完成
            this.graph.on("node:moved", ({ e, x, y, node }) => {
                // 更新连线
                // this.updateEdges();
            });

            // 节点单击
            this.graph.on("node:click", ({ e, x, y, node, view }) => {
                console.log(this.graph.getConnectedEdges(node));
            });

            // 连线完成
            this.graph.on("edge:connected", ({ isNew, edge }) => {
                // 把连线指向节点本身
                edge.setSource(edge.getSourceCell());
                edge.setTarget(edge.getTargetCell());
                // 更新连线
                // this.updateEdges();
            });

            // 连线单击
            this.graph.on("edge:click", ({ e, x, y, edge, view }) => {
                console.log(`x,y: ${x},${y}`);
                console.log(edge.getVertices());
            });

            // 双击
            this.graph.on("cell:dblclick", ({ e, x, y, cell, view }) => {
                // 双击删除节点、连线
                this.graph.removeCell(cell);
            });

            // 画布点击事件
            this.graph.on("blank:click", ({ e, x, y }) => {
                console.log(x + ", " + y);
            });
        },
        // 转换节点position为节点中心点
        alterNodeConter (node) {
            return {
                x: node.position().x + this.node_width / 2,
                y: node.position().y + this.node_height / 2
            };
        }
    },
    created () {
    },
    mounted () {
        this.getData();
        this.initGraph();
    }
};
</script>

<style scoped>
.wrapper {
    display: flex;
}
.btn-list {
    margin: 0 0 0 10px;
}
.btn {
    display: block;
    width: 50px;
    height: 20px;
    margin: 0 0 10px 0;
}

</style>
